#include "PathSearch.h"
#include <iostream>



namespace fullsail_ai { namespace algorithms {

	bool PathSearch::Distance( PlannerNode* const& p1,  PlannerNode* const& p2)
	{
		if(p1->m_dDist > p2->m_dDist)
			return true;
		else
			return false;
	}
	
	PathSearch::PathSearch() : m_bIsDone(false), m_qList(Distance)
	{
	}

	PathSearch::~PathSearch()
	{
	}

	void PathSearch::initialize(TileMap* _tileMap)
	{
		this->m_pTileMap = _tileMap;
	}

	void PathSearch::enter(int startRow, int startColumn, int goalRow, int goalColumn)
	{
		this->m_pGoal = this->m_pTileMap->getTile(goalRow, goalColumn);
		this->m_qList.push(new PlannerNode(this->m_pTileMap->getTile(startRow, startColumn), NULL, m_pGoal));
		this->m_mHash[this->m_qList.front()->m_pTile] = this->m_qList.front();
		this->m_bIsDone = false;
	}

	void PathSearch::update(long timeslice)
	{
		PlannerNode* pCurrent;
		PlannerNode* pSuccessor;
		Tile*		 pAdjTile;
		static int nodeCount = 1;

		while(!this->m_qList.empty() && 0 <= timeslice)
		{
			pCurrent = this->m_qList.front();

			pCurrent->m_pTile->setFill(0xff0000ff);
			this->m_qList.pop();

			
			if(pCurrent->m_pTile == this->m_pGoal)
			{
				// exit your found the goal
				nodeCount = this->m_mHash.size();
				std::cout << "Node Count:" << nodeCount << '\n';
				this->m_bIsDone = true;
				return;
			}

			for(int nCurrentNode = 0; nCurrentNode < 8; ++nCurrentNode)
			{
				switch(nCurrentNode)
				{
				case 0:
					pAdjTile = this->m_pTileMap->getTile(pCurrent->m_pTile->getRow()-1, pCurrent->m_pTile->getColumn()-1);
					break;
				case 1:
					pAdjTile = this->m_pTileMap->getTile(pCurrent->m_pTile->getRow(),   pCurrent->m_pTile->getColumn()-1);
					break;
				case 2:
					pAdjTile = this->m_pTileMap->getTile(pCurrent->m_pTile->getRow()-1, pCurrent->m_pTile->getColumn());
					break;
				case 3:
					pAdjTile = this->m_pTileMap->getTile(pCurrent->m_pTile->getRow()+1, pCurrent->m_pTile->getColumn()-1);
					break;
				case 4:
					pAdjTile = this->m_pTileMap->getTile(pCurrent->m_pTile->getRow()-1, pCurrent->m_pTile->getColumn()+1);
					break;
				case 5: 
					pAdjTile = this->m_pTileMap->getTile(pCurrent->m_pTile->getRow(),   pCurrent->m_pTile->getColumn()+1);
					break;
				case 6:
					pAdjTile = this->m_pTileMap->getTile(pCurrent->m_pTile->getRow()+1, pCurrent->m_pTile->getColumn());
					break;
				case 7:
					pAdjTile = this->m_pTileMap->getTile(pCurrent->m_pTile->getRow()+1, pCurrent->m_pTile->getColumn()+1);
					break;
				default:
					pAdjTile = NULL;
					break;
				};
			
				if(pAdjTile && pAdjTile->getWeight() != 0)
				{
					if(this->AreAdjacent(pCurrent->m_pTile, pAdjTile))
					{
						pAdjTile->setOutline(0xffffdd00);
						//check if already in hash... duh
						if(this->m_mHash[pAdjTile] == NULL)
						{
							pSuccessor = new PlannerNode(pAdjTile, pCurrent, m_pGoal);
							this->m_mHash[pAdjTile] = pSuccessor;
							this->m_qList.push(pSuccessor);
						}
					}
				}
			}
			while(NULL != pCurrent->m_pParent && pCurrent != NULL)
			{
				pCurrent->m_pTile->setLineTo(pCurrent->m_pParent->m_pTile, 0xffff0000);
				pCurrent = pCurrent->m_pParent;
			}
			--timeslice;
		}
	}

	void PathSearch::exit()
	{
		std::map<Tile const*, PlannerNode*>::iterator iter;
		PlannerNode* deleteThis;
		for(iter = this->m_mHash.begin();
			iter != this->m_mHash.end(); )
		{
			deleteThis = iter->second;
			iter++;
			delete deleteThis;
		}
		this->m_mHash.clear();

		this->m_qList.clear();

	}

	void PathSearch::shutdown()
	{
		exit();
	}

	bool PathSearch::isDone() const
	{
		return this->m_bIsDone;
	}

	std::vector<Tile const*> const PathSearch::getSolution() const
	{
		std::vector<Tile const*> temp;
		return temp;
	}



	bool PathSearch::AreAdjacent(Tile const* lhs, Tile const* rhs)
	{
		if(lhs->getRow()%2)
		{
			// odd
			if(rhs->getColumn() < lhs->getColumn() 
				&& (rhs->getRow() > lhs->getRow() 
				|| rhs->getRow() < lhs->getRow()))
			{
				return false;
			}
			return true;			
		}
		else
		{
			// even
			if(rhs->getColumn() > lhs->getColumn() 
				&& (rhs->getRow() > lhs->getRow() 
				|| rhs->getRow() < lhs->getRow()))
			{
				return false;
			}
			return true;
		}
	}

}}  // namespace fullsail_ai::algorithms

